﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Formatting;
using System.Text;
using System.Threading.Tasks;

namespace gt.framework.Util
{
    public static class HttpClientUtils
    {
        private static HttpClient m_client = new HttpClient() { Timeout = TimeSpan.FromSeconds(10) };
        private const string ContentType_Json = "application/json";

        public async static Task<T> GetJson<T>(string url)
        {
            return await GetJson<T>(url, null).ConfigureAwait(false);
        }
        public async static Task<T> GetJson<T>(string url, Dictionary<string, string> heads)
        {
            Uri uri = Convert(url);
            using (var message = new HttpRequestMessage(HttpMethod.Get, uri))
            {
                AddHttpMessageHead(message, heads);
                return await Send<T>(message).ConfigureAwait(false);
            }
        }
        public async static Task<string> GetString(string url)
        {
            return await GetString(url, null).ConfigureAwait(false);
        }
        public async static Task<string> GetString(string url, Dictionary<string, string> heads)
        {
            Uri uri = Convert(url);
            using (var message = new HttpRequestMessage(HttpMethod.Get, uri))
            {
                AddHttpMessageHead(message, heads);
                return await Send(message).ConfigureAwait(false);
            }
        }

        public async static Task<T> PostAsJson<T, R>(string url, R data)
        {
            return await PostAsJson<T, R>(url, data, null).ConfigureAwait(false);
        }
        public async static Task<T> PostAsJson<T, R>(string url, R data, Dictionary<string, string> heads)
        {
            Uri uri = Convert(url);
            using (var message = new HttpRequestMessage(HttpMethod.Post, uri)
            {
                Content = new ObjectContent<R>(data, new JsonMediaTypeFormatter(), ContentType_Json)
            })
            {
                AddHttpMessageHead(message, heads);
                return await Send<T>(message).ConfigureAwait(false);
            }
        }
        public async static Task<string> Post(string url, string jsonStr)
        {
            return await Post(url, jsonStr, null).ConfigureAwait(false);
        }
        public async static Task<string> Post(string url, string jsonStr, Dictionary<string, string> heads)
        {
            Uri uri = Convert(url);
            using (var message = new HttpRequestMessage(HttpMethod.Post, uri)
            {
                Content = new StringContent(jsonStr, Encoding.UTF8, ContentType_Json)
            })
            {
                AddHttpMessageHead(message, heads);
                return await Send(message).ConfigureAwait(false);
            }
        }
        public async static Task<string> Post(string url, HttpContent content, Dictionary<string, string> heads)
        {
            Uri uri = Convert(url);
            using (var message = new HttpRequestMessage(HttpMethod.Post, uri) { Content = content })
            {
                AddHttpMessageHead(message, heads);
                return await Send(message).ConfigureAwait(false);
            }
        }
        public async static Task<T> Send<T>(HttpRequestMessage message)
        {
            var response = await m_client.SendAsync(message, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);
            return await response.Content.ReadAsAsync<T>().ConfigureAwait(false);
        }
        public async static Task<string> Send(HttpRequestMessage message)
        {
            var response = await m_client.SendAsync(message, HttpCompletionOption.ResponseContentRead).ConfigureAwait(false);
            return await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        }

        #region private

        private static Uri Convert(string url)
        {
            if (string.IsNullOrEmpty(url)) throw new ArgumentNullException("url");
            return new Uri(url);
        }
        private static void AddHttpMessageHead(HttpRequestMessage message, Dictionary<string, string> heads)
        {
            if (heads == null) return;
            foreach (var head in heads)
            {
                message.Headers.Add(head.Key, head.Value);
            }
        }

        #endregion

        public static string GetLocalIp()
        {
            string ip = "0.0.0.0";
            try
            {
                var ipArray = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
                if (ipArray != null && ipArray.Length != 0)
                {
                    var ip4 = ipArray.FirstOrDefault(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
                    if (ip4 != null) ip = ip4.ToString();
                }
            }
            catch { }
            return ip;
        }
    }
}
